package com.tsfyun.scm.service.impl.logistics;

import cn.hutool.core.collection.CollectionUtil;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.tsfyun.common.base.exception.ServiceException;
import com.tsfyun.common.base.extension.OrderItem;
import com.tsfyun.common.base.util.StringUtils;
import com.tsfyun.common.base.util.TsfPreconditions;
import com.tsfyun.scm.dto.logistics.TransportSupplierDTO;
import com.tsfyun.scm.dto.logistics.TransportSupplierPlusInfoDTO;
import com.tsfyun.scm.dto.logistics.TransportSupplierQTO;
import com.tsfyun.scm.entity.logistics.Conveyance;
import com.tsfyun.scm.entity.logistics.TransportSupplier;
import com.tsfyun.scm.mapper.logistics.TransportSupplierMapper;
import com.tsfyun.scm.service.logistics.IConveyanceService;
import com.tsfyun.scm.service.logistics.ITransportSupplierService;
import com.tsfyun.common.base.extension.ServiceImpl;
import com.tsfyun.scm.util.TsfWeekendSqls;
import com.tsfyun.scm.vo.logistics.ConveyanceVO;
import com.tsfyun.scm.vo.logistics.SimpleTransportSupplierVO;
import com.tsfyun.scm.vo.logistics.TransportSupplierPlusVO;
import com.tsfyun.scm.vo.logistics.TransportSupplierVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import tk.mybatis.mapper.entity.Example;
import tk.mybatis.mapper.weekend.WeekendSqls;

import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *

 * @since 2020-03-20
 */
@Service
public class TransportSupplierServiceImpl extends ServiceImpl<TransportSupplier> implements ITransportSupplierService {

    @Autowired
    private IConveyanceService conveyanceService;

    @Autowired
    private TransportSupplierMapper transportSupplierMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public Long addPlus(TransportSupplierPlusInfoDTO dto) {
        TransportSupplierDTO transportSupplierDTO = dto.getTransportSupplier();
        //保存运输供应商信息
        TransportSupplier supplier = simpleAdd(transportSupplierDTO);
        //保存运输工具
        conveyanceService.addBatch(supplier.getId(),dto.getConveyances());
        return supplier.getId();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void editPlus(TransportSupplierPlusInfoDTO dto) {
        TransportSupplierDTO transportSupplierDTO = dto.getTransportSupplier();
        //修改运输供应商信息
        simpleEdit(transportSupplierDTO);
        //删除供应商运输工具信息
        conveyanceService.removeByTransportSupplierId(transportSupplierDTO.getId());
        //批量保存供应商运输工具信息
        conveyanceService.addBatch(transportSupplierDTO.getId(),dto.getConveyances());
    }

    @Override
    public TransportSupplierPlusVO detailPlus(Long id) {
        TransportSupplier transportSupplier = super.getById(id);
        TsfPreconditions.checkArgument(Objects.nonNull(transportSupplier),new ServiceException("运输供应商信息不存在"));
        //获取车辆信息
        List<Conveyance> conveyances = conveyanceService.list(id);
        if(CollectionUtil.isNotEmpty(conveyances)) {
            conveyances = conveyances.stream().sorted(Comparator.comparing(Conveyance::getIsDefault).thenComparing(Conveyance::getDateUpdated).reversed())
                    .collect(Collectors.toList());
        }
        return new TransportSupplierPlusVO(beanMapper.map(transportSupplier, TransportSupplierVO.class),beanMapper.mapAsList(conveyances, ConveyanceVO.class));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateDisabled(Long id, Boolean disabled) {
        TransportSupplier transportSupplier = super.getById(id);
        Optional.ofNullable(transportSupplier).orElseThrow(()->new ServiceException("运输供应商信息不存在"));
        TransportSupplier update = new TransportSupplier();
        update.setDisabled(disabled);
        transportSupplierMapper.updateByExampleSelective(update, Example.builder(TransportSupplier.class).where(
                WeekendSqls.<TransportSupplier>custom().andEqualTo(TransportSupplier::getId,id)
        ).build());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public TransportSupplier simpleAdd(TransportSupplierDTO dto) {
        TransportSupplier transportSupplier = beanMapper.map(dto,TransportSupplier.class);
        //校验是否存在同名供应商
        TransportSupplier condition = new TransportSupplier();
        condition.setName(dto.getName());
        TsfPreconditions.checkArgument( super.count(condition) < 1,new ServiceException(String.format("已经存在名称为：%s  的运输供应商",dto.getName())));
        transportSupplier.setDisabled(Boolean.FALSE);
        //保存供应商信息
        super.saveNonNull(transportSupplier);
        return transportSupplier;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void simpleEdit(TransportSupplierDTO dto) {
        TransportSupplier transportSupplier = super.getById(dto.getId());
        Optional.ofNullable(transportSupplier).orElseThrow(()->new ServiceException("运输供应商信息不存在"));
        transportSupplier.setDisabled(dto.getDisabled());
        transportSupplier.setAddress(dto.getAddress());
        transportSupplier.setFax(dto.getFax());
        transportSupplier.setLinkPerson(dto.getLinkPerson());
        transportSupplier.setMemo(dto.getMemo());
        transportSupplier.setTel(dto.getTel());
        //校验是否存在同名的供应商
        transportSupplier.setName(StringUtils.removeSpecialSymbol(dto.getName()));
        int count = transportSupplierMapper.selectCountByExample(Example.builder(TransportSupplier.class).where(WeekendSqls.<TransportSupplier>custom()
                .andEqualTo(TransportSupplier::getName,transportSupplier.getName())
                .andNotEqualTo(TransportSupplier::getId,transportSupplier.getId())).build());
        TsfPreconditions.checkArgument(count < 1,new ServiceException(String.format("已经存在名称为：%s  的运输供应商",transportSupplier.getName())));
        super.updateById(transportSupplier);
    }

    @Override
    public PageInfo<TransportSupplier> pageList(TransportSupplierQTO qto) {
        TsfWeekendSqls sqls = TsfWeekendSqls.<TransportSupplier>custom()
                .andLike(true, TransportSupplier::getName,qto.getName())
                .andLike(true, TransportSupplier::getLinkPerson,qto.getLinkPerson())
                .andEqualTo(true,TransportSupplier::getDisabled,qto.getDisabled());
        return super.pageList(qto.getPage(),qto.getLimit(),sqls, Lists.newArrayList(OrderItem.desc("dateCreated")));
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void remove(Long id) {
        //如果运输供应商下面有运输工具，暂不允许删除，以免误删
        int conveyanceCount = conveyanceService.countByTransportSupplierId(id);
        TsfPreconditions.checkArgument(conveyanceCount < 1,new ServiceException(String.format("该运输供应商下面存在%d条运输工具信息，不允许删除",conveyanceCount)));
        //其他业务数据，冗余，不做检查
        try {
            super.removeById(id);
        } catch (DataIntegrityViolationException e) {
            throw new ServiceException("当前运输供应商存在关联性数据，不允许删除");
        }
    }

    @Override
    public List<SimpleTransportSupplierVO> select( ) {
        TransportSupplier condition = new TransportSupplier();
        condition.setDisabled(Boolean.FALSE);
        List<TransportSupplier> suppliers =  super.list(condition);
        //按修改时间排序
        suppliers = suppliers.stream().sorted(Comparator.comparing(TransportSupplier::getDateUpdated).reversed()).collect(Collectors.toList());
        return beanMapper.mapAsList(suppliers,SimpleTransportSupplierVO.class);
    }
}
